//Copyright 2010 Balazs Keri, Imre Keri
//
//This file is part of FireworksCreator.
//
//FireworksCreator is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//FireworksCreator is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with FireworksCreator.  If not, see <http://www.gnu.org/licenses/>.
//
#include <global.h>
#include <QtDebug>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QSplitter>
#include <model/root.h>
#include <model/group.h>
#include "actiondispatcher.h"
#include "document.h"
#include "modeldataobjectadapters.h"
#include "objectstab.h"
#include "objtreeview.h"
#include "primitives.h"
#include "primitivegroup.h"
#include "playerwindow.h"
#include "objectpage.h"//tmp
#include "simpletextview.h"
#include "displayview.h"
#include "viewattributegroup.h"
#include "viewattributes.h"
#include "mainview.h"
using namespace model;
//
MainView::MainView(QWidget *parent)
:
   QMainWindow(parent),
   dispatcher(new ActionDispatcher(this))
{
   ui.setupUi(this);
   //connectActions
   QObject::connect(ui.action_test,SIGNAL(triggered(bool)),this,SLOT(do_test()));
   QObject::connect(ui.action_new_fireworks,SIGNAL(triggered(bool)),this,SLOT(new_fireworks()));
   QObject::connect(ui.action_open,SIGNAL(triggered(bool)),this,SLOT(fireworks_open()));
   QObject::connect(ui.action_save,SIGNAL(triggered(bool)),this,SLOT(fireworks_save()));
   QObject::connect(ui.action_save_as,SIGNAL(triggered(bool)),this,SLOT(fireworks_save_as()));
   QObject::connect(ui.action_close,SIGNAL(triggered(bool)),this,SLOT(fireworks_close()));
   QObject::connect(ui.action_undo,SIGNAL(triggered(bool)),this,SLOT(edit_undo()));
   QObject::connect(ui.action_redo,SIGNAL(triggered(bool)),this,SLOT(edit_redo()));
   QObject::connect(ui.action_exit,SIGNAL(triggered(bool)),this,SLOT(app_exit()));
   dispatcher->register_action(ui.action_create_particle_template);
   dispatcher->register_action(ui.action_create_emitter_template);
   dispatcher->register_action(ui.action_create_group);
   dispatcher->register_action(ui.action_delete);
   //createWidgets
   central_widget=new QSplitter(this);
   root_tree=new ObjTreeView(this,0,true,true);
   connect(root_tree,SIGNAL(double_clicked(Identified*)),this,SLOT(on_root_tree_double_clicked(Identified*)));
   //QHBoxLayout *layout=new QHBoxLayout();
   //layout->addWidget(central_view);
   //central_widget->setLayout(layout);
   objects_tab=new ObjectsTab(this,0);
   central_widget->addWidget(root_tree);
   central_widget->addWidget(objects_tab);
   setCentralWidget(central_widget);
   stxt_view=new SimpleTextView();
   stxt_view->show();
   displ_view=new DisplayView();
   displ_view->show();
   //other
   re_enable_actions();
   set_undo_redo_actions();
   refresh_window_title();
}
MainView::~MainView()
{
}
ActionDispatcher *MainView::get_act_dispatcher() const
{
   return dispatcher.data();
}
void MainView::set_attr_group_all(const QSharedPointer<ViewAttributeGroup> &p_ag)
{
   set_attr_group(p_ag);
   root_tree->set_attr_group(p_ag);
   objects_tab->set_attr_group(p_ag);
   stxt_view->set_attr_group(p_ag);
   displ_view->set_attr_group(p_ag);
}
void MainView::re_create_attr_groups(Document *p_doc)
{
   //new_ag->add_attribute(new ViewAttributeType::ParticleTemplate(new_ag, selected_particle_template));
   //new ViewAttributeType::ParticleTemplate(new_ag,selected_particle_template);
   QSharedPointer<ViewAttributeGroup> new_ag(new ViewAttributeGroup(p_doc));
   ViewAttributeType::ModelDataObject *const root_attr=new ViewAttributeType::ModelDataObject(new_ag,root_object);
   set_attr_group_all(new_ag);
   root_attr->set_object(p_doc?p_doc->get_root()->root_group:0);
}
void MainView::replace_document(Document *p_new_doc)
{
   Document *old_doc=get_document();
   if(p_new_doc)
   {
      re_create_attr_groups(p_new_doc);
      connect(p_new_doc,SIGNAL(history_changed()),SLOT(on_document_history_changed()));
      connect(p_new_doc,SIGNAL(modified_changed(bool)),SLOT(on_document_modified_changed(bool)));
   }
   else
   {
      set_attr_group_all(QSharedPointer<ViewAttributeGroup>());
   }
   if(old_doc)
      delete old_doc;
}
bool MainView::allowed_to_delete()
{
   Document *doc=get_document();
   if(!doc)
      return true;
   if(!doc->get_modified())
      return true;
   QMessageBox::StandardButton choice=QMessageBox::question(0,tr("File has unsaved changes"),tr("Save changes to %1?").arg(file_name.isEmpty()?tr("(new fireworks)"):file_name),QMessageBox::Yes|QMessageBox::No,QMessageBox::Yes);
   if(choice==QMessageBox::Yes)
   {
      if(!try_fireworks_save())
         return false;
   }
   else if(choice!=QMessageBox::No)
      return false;
   return true;
}
void MainView::refresh_window_title()
{
   if(get_document())
   {
      setWindowTitle(QString());
      if(!file_name.isEmpty())
         setWindowFilePath(file_name);
      else
         setWindowFilePath(tr("untitled.fwc"));
      setWindowModified(get_document()->get_modified());
   }
   else
   {
      setWindowTitle(tr("FireworksCreator"));
   }
}
void MainView::re_enable_actions()
{
   const bool doc_exists=get_document()!=0;
   ui.action_save->setEnabled(doc_exists);
   ui.action_save_as->setEnabled(doc_exists);
   ui.action_close->setEnabled(doc_exists);
}
void MainView::set_undo_redo_actions()
{
   const Document *doc=this->get_document();
   if(!doc)
   {
      ui.action_undo->setEnabled(false);
      ui.action_undo->setText(tr("Undo","action"));
      ui.action_redo->setEnabled(false);
      ui.action_redo->setText(tr("Redo","action"));
   }
   else
   {
      QString undo_desc=doc->get_undo_op_description();
      QStringList redo_desc=doc->get_redo_op_descriptions();
      ui.action_undo->setEnabled(!undo_desc.isNull());
      if(undo_desc.isNull())
         ui.action_undo->setText(tr("Undo","action"));
      else
         ui.action_undo->setText(tr("Undo: %1","action").arg(undo_desc));
      ui.action_redo->setEnabled(!redo_desc.empty());
      if(redo_desc.empty())
         ui.action_redo->setText(tr("Redo","action"));
      else
         ui.action_redo->setText(tr("Redo: %1","action").arg(redo_desc.front()));
   }
}
bool MainView::try_fireworks_save()
{
   if(!get_document())
      return true;
   if(file_name.isEmpty())
   {
      return try_fireworks_save_as();
   }
   if(get_document()->save(file_name))
   {
      get_document()->set_modified(false);
      refresh_window_title();
      return true;
   }
   return false;
}
bool MainView::try_fireworks_save_as()
{
   if(!get_document())
      return true;
   QFileDialog fd(0,Qt::Dialog);
   fd.setFileMode(QFileDialog::AnyFile);
   fd.setNameFilter(tr("FireworksCreator files (*.fwc)"));
   fd.setViewMode(QFileDialog::List);
   fd.setWindowTitle(tr("Save fireworks as"));
   fd.setLabelText(QFileDialog::Accept, tr("Save"));
   if (!fd.exec())
      return false;
   QFileInfo fi(fd.selectedFiles().at(0));
   QString new_file_name(fi.absoluteFilePath());
   if(fi.suffix().isEmpty())
   {
      if (new_file_name.endsWith('.'))
         new_file_name.append("fwc");
      else
         new_file_name.append(".fwc");
   }
   if(!get_document()->save(new_file_name))
      return false;
   file_name=new_file_name;
   get_document()->set_modified(false);
   refresh_window_title();
   return true;
}
//
void MainView::closeEvent(QCloseEvent *evnt)
{
   if(allowed_to_delete())
      evnt->accept();
   else
      evnt->ignore();
}
void MainView::new_fireworks()
{
   if(!allowed_to_delete())
      return;
   Document *new_doc=new Document;
   new_doc->initialize_new();
   file_name.clear();
   replace_document(new_doc);
}
void MainView::fireworks_open()
{
   if(!allowed_to_delete())
      return;
   QFileDialog fd(0,Qt::Dialog);
   fd.setFileMode(QFileDialog::ExistingFile);
   fd.setNameFilter(tr("FireworksCreator files (*.fwc)"));
   fd.setViewMode(QFileDialog::List);
   fd.setWindowTitle(tr("Open fireworks"));
   fd.setLabelText(QFileDialog::Accept,tr("Open"));
   if (!fd.exec())
      return;
   Document *new_doc=new Document;
   if (!new_doc->load(fd.selectedFiles().at(0)))
   {
      delete new_doc;
      return;
   }
   file_name=fd.selectedFiles().at(0);
   replace_document(new_doc);
}
void MainView::fireworks_save()
{
   try_fireworks_save();
}
void MainView::fireworks_save_as()
{
   try_fireworks_save_as();
}
void MainView::fireworks_close()
{
   if(!allowed_to_delete())
      return;
   replace_document(0);
}
void MainView::app_exit()
{
   if(!allowed_to_delete())
      return;
   qApp->quit();
}
void MainView::edit_undo()
{
   Document *doc=this->get_document();
   if(doc)
      doc->undo();
}
void MainView::edit_redo()
{
   Document *doc=this->get_document();
   if(doc)
      doc->redo(0);
}
void MainView::on_root_tree_double_clicked(Identified *object)
{
   //objects_tab->open_page(object);
   create_test_view(object);
}
void MainView::on_document_history_changed()
{
   this->set_undo_redo_actions();
}
void MainView::on_document_modified_changed(bool)
{
   this->refresh_window_title();
}
//
void MainView::handle_set_attr_group()
{
   re_enable_actions();
   set_undo_redo_actions();
   refresh_window_title();
}
void MainView::handle_post_primitive_group(const PrimitiveGroup &p_primitive_group)
{
   qDebug() << "MainView: post_primitive_group " << p_primitive_group.get_description();
}
//
void MainView::do_test()
{
   PlayerWindow *player_window=new PlayerWindow(0);
   player_window->setAttribute(Qt::WA_DeleteOnClose);
   player_window->resize(500,500);
   player_window->show();
}
void MainView::create_test_view(Identified *p_obj)
{
   QWidget *w=new QWidget(0);
   ObjectPage *page=ModelDataObjectAdapter::get_adapter(p_obj->metaObject()->className())->create_page(this,w);
   QHBoxLayout *l=new QHBoxLayout(w);
   if(page)
   {
      l->addWidget(page);
      page->set_object(p_obj);
   }
   w->setLayout(l);
   w->show();
}
